//#define __USE_TIME_BITS64
#include <time.h>
#include <string>
#include <stdexcept>
#include <string>

#include "debug.hpp"
#include "misc.hpp"

#include "tinySeqFile.hpp"

using namespace wheels;

bool tinySeqFile::aes128_write__(const std::string& data) {
    (void)data;
    throw std::runtime_error("加密功能尚未实现。当前版本仅支持明文(emCrypto::NONE)。");
    return false;
}

bool tinySeqFile::aes128_write__(const wheels::mallocSharedPtr<uint8_t> data) {
    (void)data;
    throw std::runtime_error("加密功能尚未实现。当前版本仅支持明文(emCrypto::NONE)。");
    return false;
}

bool tinySeqFile::aes256_write__(const std::string& data) {
    (void)data;
    throw std::runtime_error("加密功能尚未实现。当前版本仅支持明文(emCrypto::NONE)。");
    return false;
}

bool tinySeqFile::aes256_write__(const wheels::mallocSharedPtr<uint8_t> data) {
    (void)data;
    throw std::runtime_error("加密功能尚未实现。当前版本仅支持明文(emCrypto::NONE)。");
    return false;
}

bool tinySeqFile::aes128_read__(std::string& data) {
    (void)data;
    throw std::runtime_error("加密功能尚未实现。当前版本仅支持明文(emCrypto::NONE)。");
    return false;
}

bool tinySeqFile::aes128_read__(wheels::mallocSharedPtr<uint8_t> data) {
    (void)data;
    throw std::runtime_error("加密功能尚未实现。当前版本仅支持明文(emCrypto::NONE)。");
    return false;
}

bool tinySeqFile::aes256_read__(std::string& data) {
    (void)data;
    throw std::runtime_error("加密功能尚未实现。当前版本仅支持明文(emCrypto::NONE)。");
    return false;
}

bool tinySeqFile::aes256_read__(wheels::mallocSharedPtr<uint8_t> data) {
    (void)data;
    throw std::runtime_error("加密功能尚未实现。当前版本仅支持明文(emCrypto::NONE)。");
    return false;
}

bool tinySeqFile :: sync__()
{   
    if (m_is_synced__ || !m_fs__.is_open()) {
        return true;
    }
    MSG( "同步数据信息" , TBLUE );
    // 同步stHead（含m_curr_idx）到文件头
    m_fs__.seekp(0);
    if (!m_fs__.write(reinterpret_cast<const char*>(&m_head__), sizeof(stHead)).good()) {
        return false;
    }

    // 同步有效索引到文件索引区
    for (const auto& item : m_idxs__) {
        size_t idx_off = sizeof(stHead) + (item.first % m_head__.m_max_count) * sizeof(stIndexItem);
        m_fs__.seekp(idx_off);
        if (!m_fs__.write(reinterpret_cast<const char*>(&item.second), sizeof(stIndexItem)).good()) {
            return false;
        }
    }

    m_is_synced__ = true;
    return true;
}

tinySeqFile :: tinySeqFile( const std::string& path , uint64_t count , uint32_t page  )
    :m_is_synced__( false ) , m_is_inited__( false )
{
    // 初始化stHead基础值
    memcpy(m_head__.m_magic, "TF\0\0", 4);
    m_head__.m_ver = 1;
    m_head__.m_count = 0;
    m_head__.m_max_count = count;
    m_head__.m_page_size = page;
    m_head__.m_crypto = static_cast<uint8_t>(emCrypto::NONE);
    m_head__.m_start_idx = 0;
    m_head__.m_curr_idx = 0;
    // 计算文件总长度
    m_head__.m_length = sizeof(stHead) + count * sizeof(stIndexItem) + static_cast<uint64_t>(count) * page;

    // 二进制模式打开文件
    std::ios_base::openmode mode = std::ios::in | std::ios::out | std::ios::binary;
    m_fs__.open(path, mode);

    if (!m_fs__.is_open()) {
        // 新建文件
        mode |= std::ios::trunc;
        m_fs__.open(path, mode);
        if (!m_fs__.is_open()) {
            throw std::runtime_error("创建文件失败: " + path);
        }

        // 写入初始stHead和空索引区
        m_fs__.write(reinterpret_cast<const char*>(&m_head__), sizeof(stHead));
        stIndexItem empty_idx = {0, 0, 0};
        for (uint64_t i = 0; i < count; ++i) {
            m_fs__.write(reinterpret_cast<const char*>(&empty_idx), sizeof(stIndexItem));
        }
        MSG( "初始化索引完成" , OK_MSG );
        mallocSharedPtr< char > buff( page );
        for( uint64_t i = 0; i < count; ++i ){
            m_fs__.write(buff.get(), page );
        }
        MSG( "初始化存储区完成" , OK_MSG );
        m_is_synced__ = true;
        m_is_inited__ = true;
    } else {
        // 加载已有文件
        m_fs__.seekg(0);
        m_fs__.read(reinterpret_cast<char*>(&m_head__), sizeof(stHead));

        // 校验文件合法性
        if (memcmp(m_head__.m_magic, "TF\0\0", 4) != 0) {
            throw std::runtime_error("文件魔数无效");
        }
        if (m_head__.m_ver != 1) {
            throw std::runtime_error("文件版本不支持: " + std::to_string(m_head__.m_ver));
        }

        // 加载索引到内存
        stIndexItem item;
        for (uint64_t i = 0; i < m_head__.m_max_count; ++i) {
            m_fs__.read(reinterpret_cast<char*>(&item), sizeof(stIndexItem));
            if (item.m_len > 0 && item.m_len <= page) {
                m_idxs__[item.m_idx] = item;
            }
        }
        m_is_synced__ = true;
        m_is_inited__ = true;
    }
}
tinySeqFile :: ~tinySeqFile()
{
    mutexUniqueLock(lock, m_mutex__);
    if (m_fs__.is_open()) {
        sync__();
        m_fs__.flush();
        m_fs__.close();
    }
}

bool tinySeqFile :: setCrypto( emCrypto type , std::string& key , std::string& iv )
{
    bool ret = true;

    mutexUniqueLock(lock, m_mutex__);

    // 仅空队列可配置加密
    if (m_head__.m_count > 0) {
        return false;
    }

    // 校验密钥/IV长度
    switch (type) {
        case emCrypto::NONE:
            m_head__.m_crypto = 0;
            m_aes_key.clear();
            m_aes_iv.clear();
            break;
        case emCrypto::AES128:
            if (key.size() != 16 || iv.size() != 16) return false;
            m_head__.m_crypto = 1;
            m_aes_key = key;
            m_aes_iv = iv;
            break;
        case emCrypto::AES256:
            if (key.size() != 32 || iv.size() != 16) return false;
            m_head__.m_crypto = 2;
            m_aes_key = key;
            m_aes_iv = iv;
            break;
        default:
            return false;
    }

    m_is_synced__ = false;
    ret = sync__();
    return ret;
}

bool tinySeqFile :: push( const std::string& data )
{
    bool ret = true;

    mutexUniqueLock(lock, m_mutex__);
    if (data.empty()){
        ERROR_MSG( "数据内容空" );
        return false;
    }
    if( m_is_inited__ == false ){
        return false;
    }
    const auto crypto = static_cast<emCrypto>(m_head__.m_crypto);
    const uint64_t max_cnt = m_head__.m_max_count;
    const uint32_t page = m_head__.m_page_size;
    bool write_ok = false;

    // 队列满则覆盖队头
    if (m_head__.m_count >= max_cnt) {
        if (m_head__.m_count != 0 ){
            const uint64_t front_idx = m_head__.m_start_idx;
            m_idxs__.erase(front_idx);

            // 标记文件索引为无效
            const uint64_t file_idx = front_idx % m_head__.m_max_count;
            const size_t idx_off = sizeof(stHead) + file_idx * sizeof(stIndexItem);
            stIndexItem empty_idx = {front_idx, 0, 0L };
            m_fs__.seekp(idx_off);
            m_fs__.write(reinterpret_cast<const char*>(&empty_idx), sizeof(stIndexItem));

            // 更新元数据
            m_head__.m_count--;
            m_head__.m_start_idx++;
            m_is_synced__ = false;
        }
    }

    // 计算偏移
    const int64_t file_idx = m_head__.m_curr_idx % max_cnt;
    const size_t idx_off = sizeof(stHead) + file_idx * sizeof(stIndexItem);
    const size_t data_off = sizeof(stHead) + max_cnt * sizeof(stIndexItem) + file_idx * page;

    // 按加密类型写入
    uint32_t real_len = static_cast<uint32_t>(data.size());
    switch (crypto) {
        case emCrypto::NONE:
            real_len = std::min(real_len, page);
            m_fs__.seekp(data_off);
            MSG_1( "写入数据(%d)--(%d) " , TYELLOW , real_len , data_off );
            write_ok = m_fs__.write(data.c_str(), real_len).bad();
            break;
        case emCrypto::AES128:
            write_ok = aes128_write__(data);
            break;
        case emCrypto::AES256:
            write_ok = aes256_write__(data);
            break;
        default:
            ERROR_MSG("当前版本仅支持明文(emCrypto::NONE)。");
            return false;
    }

    if(write_ok){
        MSG_1( "写入数据失败: %s" , TRED , strerror( errno) );
        return false;
    }

    // 更新索引
    m_idxs__.erase(m_head__.m_curr_idx);
    stIndexItem new_idx = {m_head__.m_curr_idx, real_len, time(nullptr)};
    m_idxs__[m_head__.m_curr_idx] = new_idx;

    // 写入文件索引
    m_fs__.seekp(idx_off);
    if (m_fs__.write(reinterpret_cast<const char*>(&new_idx), sizeof(stIndexItem)).bad()) {
        m_idxs__.erase(m_head__.m_curr_idx);
        ERROR_MSG( "写入文件索引失败" );
        return false;
    }

    // 更新元数据
    m_head__.m_count++;
    m_head__.m_curr_idx++;
    m_is_synced__ = false;

    return ret;
}
bool tinySeqFile :: push( const wheels::mallocSharedPtr< uint8_t > data )
{
    bool ret = true;
    mutexUniqueLock(lock, m_mutex__);
    if (data.dataLen() == 0 ) return false;

    const auto crypto = static_cast<emCrypto>(m_head__.m_crypto);
    const uint64_t max_cnt = m_head__.m_max_count;
    const uint32_t page = m_head__.m_page_size;
    bool write_ok = false;

    // 队列满则覆盖队头
    if (m_head__.m_count >= max_cnt) {
        if (m_head__.m_count != 0 ){
            const uint64_t front_idx = m_head__.m_start_idx;
            m_idxs__.erase(front_idx);

            // 标记文件索引为无效
            const uint64_t file_idx = front_idx % m_head__.m_max_count;
            const size_t idx_off = sizeof(stHead) + file_idx * sizeof(stIndexItem);
            stIndexItem empty_idx = {front_idx, 0, 0L };
            m_fs__.seekp(idx_off);
            m_fs__.write(reinterpret_cast<const char*>(&empty_idx), sizeof(stIndexItem));

            // 更新元数据
            m_head__.m_count--;
            m_head__.m_start_idx++;
            m_is_synced__ = false;
        }
    }

    // 计算偏移
    const int64_t file_idx = m_head__.m_curr_idx % max_cnt;
    const size_t idx_off = sizeof(stHead) + file_idx * sizeof(stIndexItem);
    const size_t data_off = sizeof(stHead) + max_cnt * sizeof(stIndexItem) + file_idx * page;

    // 按加密类型写入
    uint32_t real_len = static_cast<uint32_t>(data.dataLen());
    switch (crypto) {
        case emCrypto::NONE:
            real_len = std::min(real_len, page);
            m_fs__.seekp(data_off);
            write_ok = m_fs__.write(( char *)data.get(), real_len).good();
            break;
        case emCrypto::AES128:
            write_ok = aes128_write__(data);
            break;
        case emCrypto::AES256:
            write_ok = aes256_write__(data);
            break;
        default:
            throw std::runtime_error("当前版本仅支持明文(emCrypto::NONE)。");
            return false;
    }

    if (!write_ok) return false;

    // 更新索引
    m_idxs__.erase(m_head__.m_curr_idx);
    stIndexItem new_idx = {m_head__.m_curr_idx, real_len, time(nullptr)};
    m_idxs__[m_head__.m_curr_idx] = new_idx;

    // 写入文件索引
    m_fs__.seekp(idx_off);
    if (!m_fs__.write(reinterpret_cast<const char*>(&new_idx), sizeof(stIndexItem)).good()) {
        m_idxs__.erase(m_head__.m_curr_idx);
        return false;
    }

    // 更新元数据
    m_head__.m_count++;
    m_head__.m_curr_idx++;
    m_is_synced__ = false;
    return ret;
}

bool tinySeqFile :: front( std::string& data )
{
    mutexSharedLock(lock, m_mutex__);
    if (m_head__.m_count == 0) {
        data.clear();
        return false;
    }

    const int64_t front_idx = m_head__.m_start_idx;
    const auto it = m_idxs__.find(front_idx);
    if (it == m_idxs__.end() || it->second.m_len == 0) {
        data.clear();
        return false;
    }

    const auto crypto = static_cast<emCrypto>(m_head__.m_crypto);
    const uint32_t len = it->second.m_len;
    const int64_t file_idx = front_idx % m_head__.m_max_count;
    const size_t data_off = sizeof(stHead) + m_head__.m_max_count * sizeof(stIndexItem) + file_idx * m_head__.m_page_size;

    bool read_ok = false;
    switch (crypto) {
        case emCrypto::NONE:
            data.resize(len);
            m_fs__.seekg(data_off);
            read_ok = m_fs__.read(&data[0], len).good();
            break;
        case emCrypto::AES128:
            read_ok = aes128_read__(data);
            break;
        case emCrypto::AES256:
            read_ok = aes256_read__(data);
            break;
        default:
            data.clear();
            return false;
    }

    if (!read_ok) data.clear();
    return read_ok;
}
bool tinySeqFile :: front( wheels::mallocSharedPtr< uint8_t > data )
{
    mutexSharedLock(lock, m_mutex__);
    if (m_head__.m_count == 0 || !data) return false;

    const int64_t front_idx = m_head__.m_start_idx;
    const auto it = m_idxs__.find(front_idx);
    if (it == m_idxs__.end() || it->second.m_len == 0) return false;

    const auto crypto = static_cast<emCrypto>(m_head__.m_crypto);
    const uint32_t len = it->second.m_len;
    if (data.size() < len) return false;

    const int64_t file_idx = front_idx % m_head__.m_max_count;
    const size_t data_off = sizeof(stHead) + m_head__.m_max_count * sizeof(stIndexItem) + file_idx * m_head__.m_page_size;

    bool read_ok = false;
    switch (crypto) {
        case emCrypto::NONE:
            m_fs__.seekg(data_off);
            read_ok = m_fs__.read(reinterpret_cast<char*>(data.get()), len).good();
            break;
        case emCrypto::AES128:
            read_ok = aes128_read__(data);
            break;
        case emCrypto::AES256:
            read_ok = aes256_read__(data);
            break;
        default:
            return false;
    }

    return read_ok;
}

bool tinySeqFile :: at( uint64_t idx , std::string& data )
{
    mutexSharedLock(lock, m_mutex__);

    const auto it = m_idxs__.find(idx);
    if (it == m_idxs__.end() || it->second.m_len == 0) {
        data.clear();
        return false;
    }

    const auto crypto = static_cast<emCrypto>(m_head__.m_crypto);
    const uint32_t len = it->second.m_len;
    const int64_t file_idx = idx % m_head__.m_max_count;
    const size_t data_off = sizeof(stHead) + m_head__.m_max_count * sizeof(stIndexItem) + file_idx * m_head__.m_page_size;

    bool read_ok = false;
    switch (crypto) {
        case emCrypto::NONE:
            data.resize(len);
            m_fs__.seekg(data_off);
            read_ok = m_fs__.read(&data[0], len).good();
            break;
        case emCrypto::AES128:
            read_ok = aes128_read__(data);
            break;
        case emCrypto::AES256:
            read_ok = aes256_read__(data);
            break;
        default:
            data.clear();
            return false;
    }

    if (!read_ok) data.clear();
    return read_ok;
}
bool tinySeqFile :: at( uint64_t idx , wheels::mallocSharedPtr< uint8_t > data )
{
    mutexSharedLock(lock, m_mutex__);
    if (idx < m_head__.m_start_idx || idx >= m_head__.m_curr_idx || !data) return false;

    const auto it = m_idxs__.find(idx);
    if (it == m_idxs__.end() || it->second.m_len == 0) return false;

    const auto crypto = static_cast<emCrypto>(m_head__.m_crypto);
    const uint32_t len = it->second.m_len;
    if (data.size() < len) return false;

    const int64_t file_idx = idx % m_head__.m_max_count;
    const size_t data_off = sizeof(stHead) + m_head__.m_max_count * sizeof(stIndexItem) + file_idx * m_head__.m_page_size;

    bool read_ok = false;
    switch (crypto) {
        case emCrypto::NONE:
            m_fs__.seekg(data_off);
            read_ok = m_fs__.read(reinterpret_cast<char*>(data.get()), len).good();
            break;
        case emCrypto::AES128:
            read_ok = aes128_read__(data);
            break;
        case emCrypto::AES256:
            read_ok = aes256_read__(data);
            break;
        default:
            return false;
    }

    return read_ok;
}

void tinySeqFile :: pop_front()
{
    mutexUniqueLock(lock, m_mutex__);
    if (m_head__.m_count == 0) return;

    const uint64_t front_idx = m_head__.m_start_idx;
    m_idxs__.erase(front_idx);

    // 标记文件索引为无效
    const uint64_t file_idx = front_idx % m_head__.m_max_count;
    const size_t idx_off = sizeof(stHead) + file_idx * sizeof(stIndexItem);
    stIndexItem empty_idx = {front_idx, 0, 0L };
    m_fs__.seekp(idx_off);
    m_fs__.write(reinterpret_cast<const char*>(&empty_idx), sizeof(stIndexItem));

    // 更新元数据
    m_head__.m_count--;
    m_head__.m_start_idx++;
    m_is_synced__ = false;
}
void tinySeqFile :: pop_tail()
{
    mutexUniqueLock(lock, m_mutex__);
    if (m_head__.m_count == 0) return;

    const uint64_t tail_idx = m_head__.m_curr_idx - 1;
    const auto it = m_idxs__.find(tail_idx);
    if (it == m_idxs__.end()) return;

    m_idxs__.erase(it);

    // 标记文件索引为无效
    const uint64_t file_idx = tail_idx % m_head__.m_max_count;
    const size_t idx_off = sizeof(stHead) + file_idx * sizeof(stIndexItem);
    stIndexItem empty_idx = {tail_idx, 0, 0};
    m_fs__.seekp(idx_off);
    m_fs__.write(reinterpret_cast<const char*>(&empty_idx), sizeof(stIndexItem));

    // 更新元数据
    m_head__.m_count--;
    m_head__.m_curr_idx--;
    m_is_synced__ = false;
}

bool tinySeqFile :: erase( uint64_t idx )
{
    mutexUniqueLock(lock, m_mutex__);
    if (idx < m_head__.m_start_idx || idx >= m_head__.m_curr_idx) return false;

    const auto it = m_idxs__.find(idx);
    if (it == m_idxs__.end()) return false;

    // 标记文件索引为无效
    const uint64_t file_idx = idx % m_head__.m_max_count;
    const size_t idx_off = sizeof(stHead) + file_idx * sizeof(stIndexItem);
    stIndexItem empty_idx = {idx, 0, 0};
    if (!m_fs__.seekp(idx_off).good() || !m_fs__.write(reinterpret_cast<const char*>(&empty_idx), sizeof(stIndexItem)).good()) {
        return false;
    }

    m_idxs__.erase(it);
    m_head__.m_count--;
    m_is_synced__ = false;

    return true;
}

uint64_t tinySeqFile :: count()
{
    mutexSharedLock(lock, m_mutex__);
    return m_head__.m_count;
}

bool tinySeqFile :: clear()
{
    mutexUniqueLock(lock, m_mutex__);
    if (!m_fs__.is_open()) return false;

    // 清空内存索引
    m_idxs__.clear();

    // 标记所有文件索引为无效
    const uint64_t max_cnt = m_head__.m_max_count;
    stIndexItem empty_idx = {0, 0, 0};
    for (uint64_t i = 0; i < max_cnt; ++i) {
        const size_t idx_off = sizeof(stHead) + i * sizeof(stIndexItem);
        if (!m_fs__.seekp(idx_off).good() || !m_fs__.write(reinterpret_cast<const char*>(&empty_idx), sizeof(stIndexItem)).good()) {
            return false;
        }
    }

    // 重置元数据
    m_head__.m_count = 0;
    m_head__.m_start_idx = 0;
    m_head__.m_curr_idx = 0;
    m_is_synced__ = false;

    return sync__();
}